// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameplayTagContainer.h"
#include "AbilitySystem/AuraAbilitySystemComponent.h"
#include "DataAsset/AbilityInfo.h"
#include "UI/WidgetController/AuraWidgetController.h"
#include "OverlayWidgetController.generated.h"

class UAuraAbilitySystemComponent;
class UAbilityInfo;
/**
 *	存储一些在UI上显示的信息的结构体
 *  FTableRowBase:供所有表格行结构体继承的基类
 *  
 */
USTRUCT(BlueprintType)
struct FUIWidgetRow : public FTableRowBase
{
	GENERATED_BODY()

	/** FGameplayTag:gameplay标签结构体 */
	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	FGameplayTag MessageTag; /** FGameplayTag:gameplay标签结构体 */
	
	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	FText Message = FText(); /** FText:文本结构体 */

	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	TSubclassOf<UAuraUserWidget> MessageWidget;

	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	UTexture2D* Image; /** UTexture2D: 2D纹理 */
};

//一个参数的动态多播,动态多播可以序列化和反射,所以可以分配在蓝图上执行.(委托名,参数类型,参数名称),委托名以F为前缀,Signature为结尾
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAttributeValueChangedSignature, float, NewValue); //定义当生命值改变的委托,参数为新的生命值

/** 携带UI部件行数据的委托 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMessageWidgetRowSignature,FUIWidgetRow,Row);

/**  携带能力信息的委托 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAbilityInfoSignature, FAuraAbilityInfo, Info);

/**
 * 覆层用户控件控制器层基类，继承用户控件控制器
 */
UCLASS(BlueprintType, Blueprintable)
class AURA_API UOverlayWidgetController : public UAuraWidgetController
{
	GENERATED_BODY()

public:

	/** 该函数用于在控件控制器初始化时，将属性集中的初始数值通过委托广播至对应UI元素 */
	virtual void BroadcastInitialValues() override;

	/** 该函数主要用于将属性变化事件与UI更新委托绑定，并处理技能系统初始化及效果标签的消息广播 */
	virtual void BindCallbacksToDependencies() override;

	/** 根据传入的表格和Tag返回查找到数据,返回数据类型不确定,所以用T表示,使用函数时要指定要获取数据的对应类型 */
	template <typename T>
	T* GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag& Tag);

protected:

	/** 委托：当生命值属性发生变化时触发 */
	UPROPERTY(BlueprintAssignable, Category= "UOverlayWidgetController|Attributes") //BlueprintAssignable: 蓝图中可分配事件(函数)
	FOnAttributeValueChangedSignature OnHealthChangedDelegate;

	/** 委托：当最大生命值属性发生变化时触发 */
	UPROPERTY(BlueprintAssignable, Category= "UOverlayWidgetController|Attributes")
	FOnAttributeValueChangedSignature OnMaxHealthChangedDelegate; 

	/** 委托：当法力值属性发生变化时触发 */
	UPROPERTY(BlueprintAssignable, Category= "UOverlayWidgetController|Attributes")
	FOnAttributeValueChangedSignature OnManaChangedDelegate;
	
	/** 委托：当最大法力值属性发生变化时触发 */
	UPROPERTY(BlueprintAssignable, Category= "UOverlayWidgetController|Attributes")
	FOnAttributeValueChangedSignature OnMaxManaChangedDelegate;

	/** 委托：当经验值发生变化时触发 */
	UPROPERTY(BlueprintAssignable, Category= "UOverlayWidgetController|XP")
	FOnAttributeValueChangedSignature OnXPChangedDelegate;

	/** 经验变动后的回调函数 */
	void OnXPChanged(int32 NewXP) const; 
	
	/** 消息部件数据表资源引用 */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UOverlayWidgetController|Widget Data")
	TObjectPtr<UDataTable> MessageWidgetDataTable= nullptr;

	/** 消息部件行处理委托 */
	UPROPERTY(BlueprintAssignable)
	FMessageWidgetRowSignature MessageWidgetRowDelegate;

	/** 委托: 能力信息更新时触发 */
	UPROPERTY(BlueprintAssignable,Category="UOverlayWidgetController|Messagges")
	FAbilityInfoSignature AbilityInfoDelegate;

	/** 能力信息资源引用 */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="UOverlayWidgetController|Widget Data")
	TObjectPtr<UAbilityInfo> AbilityInfo = nullptr;

	/** 初始化启动时的能力后,将信息广播给UI */
	void OnInitStartupAbilities(UAuraAbilitySystemComponent* ASC) const;
};

/** 在指定的数据表中根据GameplayTag查找对应的数据行 */
template <typename T>
T* UOverlayWidgetController::GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag& Tag)
{
	T* Row = DataTable->FindRow<T>(Tag.GetTagName(),TEXT(""));
	return Row;
}
